// 版权所有2010 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包json实现了在
// RFC 7159中定义的json编码和解码。JSON和Go值之间的映射在封送和解封送函数的文档中描述为
// 。
// 
// 请参阅“JSON and Go”以了解此软件包的介绍：
// https:
package json

import (
	"bytes"
	"encoding"
	"encoding/base64"
	"fmt"
	"math"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"sync"
	"unicode"
	"unicode/utf8"
)

// marshall返回v的JSON编码。
// 
// marshall递归遍历值v。
// 如果遇到的值实现了封送器接口
// 并且不是零指针，封送器将调用其MarshalJSON方法
// 来生成JSON。如果不存在MarshalJSON方法，但
// 值实现编码。相反，Marshall调用
// 其MarshalText方法，并将结果编码为JSON字符串。
// nil指针异常并不是严格必需的
// 而是模仿了
// UnmarshalJSON行为中类似的必需异常。
// 
// 否则，封送使用以下依赖于类型的默认编码：
// 
// 布尔值编码为JSON布尔值。
// 
// 浮点、整数和数字值编码为JSON数字。
// 
// 字符串值编码为强制为有效UTF-8的JSON字符串，
// 用Unicode替换符文替换无效字节。
// 这样JSON就可以安全地嵌入HTML<script>标记中，
// 字符串是使用HTMLSCAPE编码的，
// 它替换了“<”、“>”、“&”，U+2028和U+2029被转义为
// 到“\u003c”、“\u003e”、“\u0026”、“\u2028”和“\u2029”。
// 在使用编码器
// 时，可以通过调用SetEscapeHTML（false）禁用此替换。
// 
// 数组和切片值编码为JSON数组，但
// /[]字节编码为base64编码字符串，零切片
// 编码为空JSON值。
// 
// 结构值编码为JSON对象。
// 每个导出的结构字段都成为对象的一个成员，使用
// 字段名作为对象键，除非由于以下给出的
// 原因之一而忽略该字段。
// 
// 每个结构字段的编码可以通过存储在结构字段标记中的“json”键下的格式字符串
// 进行自定义。
// 格式字符串给出字段名称，后面可能跟一个
// 以逗号分隔的选项列表。为了在不覆盖默认字段名的情况下指定选项，名称可能为空。
// 
// 如果字段有一个空值，定义为
// false、0、一个零指针、一个零接口值，以及任何空数组、
// 切片、映射或字符串，则“忽略空”选项指定该字段应该从编码中忽略。
// 
// 作为一种特殊情况，如果字段标记为“-”，则该字段始终被忽略。
// 注意，名为“-”的字段仍然可以使用标记“-，”生成。
// 
// 结构字段标记及其含义的示例：
// 
// 
// Field int`json:“myName”`
// 
// /字段在json中显示为键“myName”，而
// /如果该字段的值为空，则该字段将从对象中忽略，如上所述。
// Field int`json:“myName，省略empty”`
// 
// /字段在json中显示为键“Field”（默认值），但如果字段为空，则跳过该字段。
// /注意前面的逗号。
// Field int`json:，省略空“`
// 
// /此包忽略此字段。
// 字段int`json:“`
// 
// 
// Field int`json:“-”`
// 
// “string”选项表示一个字段作为json存储在一个
// json编码的字符串中。它仅适用于字符串、浮点、
// 整数或布尔类型的字段。在与JavaScript程序通信时，有时会使用这种额外级别的编码：
// 
// 
// Int64String int64`json:，string“`
// 
// 如果是由
// 仅Unicode字母、数字和ASCII标点组成的非空字符串，则将使用密钥名，但引号
// 标记、反斜杠和逗号除外。
// 
// 匿名结构字段通常被封送，就像它们的内部导出字段
// 是外部结构中的字段一样，受下一段中所述的通常Go可见性规则修订
// 的约束。
// 在JSON标记中指定名称的匿名结构字段被视为具有该名称的
// 而不是匿名的。
// 接口类型的匿名结构字段被视为以该类型作为其名称，而不是匿名。
// 
// 当
// 决定对哪个字段进行封送或解封时，结构字段的Go可见性规则将针对JSON进行修改。如果同一级别上有多个字段，且该级别是嵌套最少的字段（因此将是由
// 常用Go规则选择的嵌套级别），则以下额外规则适用：
// 
// 1）在这些字段中，如果有JSON标记的字段，则只考虑标记的字段，
// 即使有多个未标记的字段，否则会发生冲突。
// 
// 2）如果只有一个字段（根据第一条规则标记或不标记），则选中该字段。
// 
// 3）否则有多个字段，全部忽略；没有错误发生。
// 
// 处理匿名结构字段在Go 1.1中是新的。
// 在Go 1.1之前，匿名结构字段被忽略。要强制忽略当前版本和早期版本中的匿名结构字段
// ，请为字段
// JSON标记“-”。
// 
// 映射值编码为JSON对象。映射的密钥类型必须是
// 字符串、整数类型或实现编码。短信收发员。映射键
// 通过应用以下规则进行排序并用作JSON对象键，
// 受上述字符串值所述的UTF-8强制：
// /-直接使用任何字符串类型的键
// /-编码。文本封送处理程序被封送
// -整数键被转换为字符串
// 
// 指针值编码为指向的值。
// 零指针编码为空JSON值。
// 
// 接口值编码为接口中包含的值。
// nil接口值编码为空JSON值。
// 
// 通道、复数和函数值不能用JSON编码。
// 试图对这样的值进行编码会导致Marshal返回
// 一个不支持的类型错误。
// 
// JSON不能表示循环数据结构，Marshal不能处理它们。将循环结构传递给封送将导致
// 错误。
// 
func Marshal(v any) ([]byte, error) {
	e := newEncodeState()

	err := e.marshal(v, encOpts{escapeHTML: true})
	if err != nil {
		return nil, err
	}
	buf := append([]byte(nil), e.Bytes()...)

	encodeStatePool.Put(e)

	return buf, nil
}

// marshallindent类似于Marshal，但应用Indent来格式化输出。
// 输出中的每个JSON元素都将从一个新行开始，以前缀
// 开头，然后是根据缩进嵌套的一个或多个缩进副本。
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
	b, err := Marshal(v)
	if err != nil {
		return nil, err
	}
	var buf bytes.Buffer
	err = Indent(&buf, b, prefix, indent)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// HTMLEscape将JSON编码的src附加到dst，并带有<、>、&、U+2028和U+2029 
// 字符串文本中的字符更改为\u003c、\u003e、\u0026、\u2028、\u2029 
// 这样JSON就可以安全地嵌入HTML<script>标记中。
// 由于历史原因，web浏览器不支持标准HTML 
// 在<script>标记中转义，因此必须使用另一种JSON编码
// 。
func HTMLEscape(dst *bytes.Buffer, src []byte) {
	// 字符只能以字符串文字形式出现，
	// 所以只需一次扫描字符串一个字节。
	start := 0
	for i, c := range src {
		if c == '<' || c == '>' || c == '&' {
			if start < i {
				dst.Write(src[start:i])
			}
			dst.WriteString(`\u00`)
			dst.WriteByte(hex[c>>4])
			dst.WriteByte(hex[c&0xF])
			start = i + 1
		}
		// 转换U+2028和U+2029（E2 80 A8和E2 80 A9）。
		if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
			if start < i {
				dst.Write(src[start:i])
			}
			dst.WriteString(`\u202`)
			dst.WriteByte(hex[src[i+2]&0xF])
			start = i + 3
		}
	}
	if start < len(src) {
		dst.Write(src[start:])
	}
}

// 封送器是由类型实现的接口，
// 可以将自己封送到有效的JSON中。
type Marshaler interface {
	MarshalJSON() ([]byte, error)
}

// 当试图对不支持的值类型进行编码时，封送处理返回UnsupportedTypeError。
type UnsupportedTypeError struct {
	Type reflect.Type
}

func (e *UnsupportedTypeError) Error() string {
	return "json: unsupported type: " + e.Type.String()
}

// 当试图对不支持的值进行编码时，封送处理返回UnsupportedValueError。
type UnsupportedValueError struct {
	Value reflect.Value
	Str   string
}

func (e *UnsupportedValueError) Error() string {
	return "json: unsupported value: " + e.Str
}

// 在Go 1.2之前，当
// 试图用无效的UTF-8序列编码字符串值。
// 从Go 1.2开始，Marshall通过
// 用Unicode替换符U+FFFD替换无效字节，将字符串强制为有效的UTF-8。
// 
// 已弃用：不再使用；为了兼容性而保留。
type InvalidUTF8Error struct {
	S string // 导致错误的整个字符串值
}

func (e *InvalidUTF8Error) Error() string {
	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
}

// MarshalleError表示调用MarshalJSON或MarshalText方法时出错。
type MarshalerError struct {
	Type       reflect.Type
	Err        error
	sourceFunc string
}

func (e *MarshalerError) Error() string {
	srcFunc := e.sourceFunc
	if srcFunc == "" {
		srcFunc = "MarshalJSON"
	}
	return "json: error calling " + srcFunc +
		" for type " + e.Type.String() +
		": " + e.Err.Error()
}

// Unwrap返回基本错误。
func (e *MarshalerError) Unwrap() error { return e.Err }

var hex = "0123456789abcdef"

// encodeState将JSON编码为字节。缓冲器
type encodeState struct {
	bytes.Buffer // 累计输出
	scratch      [64]byte

	// 跟踪我们在当前递归调用
	// path中看到的指针，以避免可能导致堆栈溢出的循环。如果ptrLevel大于
	// 则只执行相对昂贵的映射操作，然后启动检测循环，这样，如果我们在
	// 合理数量的嵌套指针深度内，我们就可以跳过这项工作。
	ptrLevel uint
	ptrSeen  map[any]struct{}
}

const startDetectingCyclesAfter = 1000

var encodeStatePool sync.Pool

func newEncodeState() *encodeState {
	if v := encodeStatePool.Get(); v != nil {
		e := v.(*encodeState)
		e.Reset()
		if len(e.ptrSeen) > 0 {
			panic("ptrEncoder.encode should have emptied ptrSeen via defers")
		}
		e.ptrLevel = 0
		return e
	}
	return &encodeState{ptrSeen: make(map[any]struct{})}
}

// jsonError是一种错误包装类型，仅供内部使用。
// 带有错误的恐慌被包装在jsonError中，以便顶级恢复
// 可以将故意恐慌与此包区分开来。
type jsonError struct{ error }

func (e *encodeState) marshal(v any, opts encOpts) (err error) {
	defer func() {
		if r := recover(); r != nil {
			if je, ok := r.(jsonError); ok {
				err = je.error
			} else {
				panic(r)
			}
		}
	}()
	e.reflectValue(reflect.ValueOf(v), opts)
	return nil
}

// error通过使用jsonError包装的err进行恐慌来中止编码。
func (e *encodeState) error(err error) {
	panic(jsonError{err})
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Pointer:
		return v.IsNil()
	}
	return false
}

func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
	valueEncoder(v)(e, v, opts)
}

type encOpts struct {
	// quoted导致在JSON字符串中对基本字段进行编码。zhong zhong
	quoted bool
	escapeHTML bool
}

type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)

var encoderCache sync.Map // map[reflect.Type]encoderFunc 

func valueEncoder(v reflect.Value) encoderFunc {
	if !v.IsValid() {
		return invalidValueEncoder
	}
	return typeEncoder(v.Type())
}

func typeEncoder(t reflect.Type) encoderFunc {
	if fi, ok := encoderCache.Load(t); ok {
		return fi.(encoderFunc)
	}

	// 要处理递归类型，请在构建映射之前使用
	// 间接函数填充映射。这个类型等待
	// real func（f）准备就绪，然后调用它。此间接
	// func仅用于递归类型。
	var (
		wg sync.WaitGroup
		f  encoderFunc
	)
	wg.Add(1)
	fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
		wg.Wait()
		f(e, v, opts)
	}))
	if loaded {
		return fi.(encoderFunc)
	}

	// 计算实际编码器并用其替换间接函数。
	f = newTypeEncoder(t, true)
	wg.Done()
	encoderCache.Store(t, f)
	return f
}

var (
	marshalerType     = reflect.TypeOf((*Marshaler)(nil)).Elem()
	textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
)

// newTypeEncoder为类型构造一个encoderFunc。
// 返回的编码器仅在AllowADR为真时检查CanAddr。
func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
	// 如果我们有一个非指针值，其类型实现了带值接收器的
	// 封送器，那么我们最好获取
	// 值的地址——否则，我们在将值强制转换到接口时会得到
	// 分配。
	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
		return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
	}
	if t.Implements(marshalerType) {
		return marshalerEncoder
	}
	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
		return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
	}
	if t.Implements(textMarshalerType) {
		return textMarshalerEncoder
	}

	switch t.Kind() {
	case reflect.Bool:
		return boolEncoder
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return intEncoder
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return uintEncoder
	case reflect.Float32:
		return float32Encoder
	case reflect.Float64:
		return float64Encoder
	case reflect.String:
		return stringEncoder
	case reflect.Interface:
		return interfaceEncoder
	case reflect.Struct:
		return newStructEncoder(t)
	case reflect.Map:
		return newMapEncoder(t)
	case reflect.Slice:
		return newSliceEncoder(t)
	case reflect.Array:
		return newArrayEncoder(t)
	case reflect.Pointer:
		return newPtrEncoder(t)
	default:
		return unsupportedTypeEncoder
	}
}

func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
	e.WriteString("null")
}

func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	if v.Kind() == reflect.Pointer && v.IsNil() {
		e.WriteString("null")
		return
	}
	m, ok := v.Interface().(Marshaler)
	if !ok {
		e.WriteString("null")
		return
	}
	b, err := m.MarshalJSON()
	if err == nil {
		// 将JSON复制到缓冲区，检查有效性。
		err = compact(&e.Buffer, b, opts.escapeHTML)
	}
	if err != nil {
		e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
	}
}

func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	va := v.Addr()
	if va.IsNil() {
		e.WriteString("null")
		return
	}
	m := va.Interface().(Marshaler)
	b, err := m.MarshalJSON()
	if err == nil {
		// 将JSON复制到缓冲区，检查有效性。
		err = compact(&e.Buffer, b, opts.escapeHTML)
	}
	if err != nil {
		e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
	}
}

func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	if v.Kind() == reflect.Pointer && v.IsNil() {
		e.WriteString("null")
		return
	}
	m, ok := v.Interface().(encoding.TextMarshaler)
	if !ok {
		e.WriteString("null")
		return
	}
	b, err := m.MarshalText()
	if err != nil {
		e.error(&MarshalerError{v.Type(), err, "MarshalText"})
	}
	e.stringBytes(b, opts.escapeHTML)
}

func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	va := v.Addr()
	if va.IsNil() {
		e.WriteString("null")
		return
	}
	m := va.Interface().(encoding.TextMarshaler)
	b, err := m.MarshalText()
	if err != nil {
		e.error(&MarshalerError{v.Type(), err, "MarshalText"})
	}
	e.stringBytes(b, opts.escapeHTML)
}

func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	if opts.quoted {
		e.WriteByte('"')
	}
	if v.Bool() {
		e.WriteString("true")
	} else {
		e.WriteString("false")
	}
	if opts.quoted {
		e.WriteByte('"')
	}
}

func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
	if opts.quoted {
		e.WriteByte('"')
	}
	e.Write(b)
	if opts.quoted {
		e.WriteByte('"')
	}
}

func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
	if opts.quoted {
		e.WriteByte('"')
	}
	e.Write(b)
	if opts.quoted {
		e.WriteByte('"')
	}
}

type floatEncoder int // 位数

func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	f := v.Float()
	if math.IsInf(f, 0) || math.IsNaN(f) {
		e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
	}

	// 通过ES6数字到字符串的转换进行转换。
	// 这与大多数其他JSON生成器匹配。
	// 见golang。org/issue/6384和golang。org/issue/14135。
	// 与fmt%g类似，但指数截止值不同
	// 并且指数本身没有填充到两位数。
	b := e.scratch[:0]
	abs := math.Abs(f)
	fmt := byte('f')
	// 注意：必须对基础float32值使用float32比较，以获得准确的截止值。
	if abs != 0 {
		if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
			fmt = 'e'
		}
	}
	b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
	if fmt == 'e' {
		// 清理Go1中从e-09到e-9的
		n := len(b)
		if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
			b[n-2] = b[n-1]
			b = b[:n-1]
		}
	}

	if opts.quoted {
		e.WriteByte('"')
	}
	e.Write(b)
	if opts.quoted {
		e.WriteByte('"')
	}
}

var (
	float32Encoder = (floatEncoder(32)).encode
	float64Encoder = (floatEncoder(64)).encode
)

func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	if v.Type() == numberType {
		numStr := v.String()
		// 。5空字符串编码为“0”，而这不是一个有效的数字文字
		// 我们保持兼容性，因此在此之后检查有效性。
		if numStr == "" {
			numStr = "0" // 数字的零值
		}
		if !isValidNumber(numStr) {
			e.error(fmt.Errorf("json: invalid number literal %q", numStr))
		}
		if opts.quoted {
			e.WriteByte('"')
		}
		e.WriteString(numStr)
		if opts.quoted {
			e.WriteByte('"')
		}
		return
	}
	if opts.quoted {
		e2 := newEncodeState()
		// 因为我们对字符串进行了两次编码，所以第一次只需要转义HTML 
		// 即可。
		e2.string(v.String(), opts.escapeHTML)
		e.stringBytes(e2.Bytes(), false)
		encodeStatePool.Put(e2)
	} else {
		e.string(v.String(), opts.escapeHTML)
	}
}

// isValidNumber报告s是否为有效的JSON数字文本。
func isValidNumber(s string) bool {
	// 此函数实现JSON数字语法。
	// 参见https:
	// 和https:

	if s == "" {
		return false
	}

	// 可选-
	if s[0] == '-' {
		s = s[1:]
		if s == "" {
			return false
		}
	}

	// 数字
	switch {
	default:
		return false

	case s[0] == '0':
		s = s[1:]

	case '1' <= s[0] && s[0] <= '9':
		s = s[1:]
		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
			s = s[1:]
		}
	}

	// 。后跟一个或多个数字。
	if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
		s = s[2:]
		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
			s = s[1:]
		}
	}

	// e或e后跟可选的-或+和
	// 1个或更多数字。
	if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
		s = s[1:]
		if s[0] == '+' || s[0] == '-' {
			s = s[1:]
			if s == "" {
				return false
			}
		}
		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
			s = s[1:]
		}
	}

	// 确保我们在最后。
	return s == ""
}

func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
	if v.IsNil() {
		e.WriteString("null")
		return
	}
	e.reflectValue(v.Elem(), opts)
}

func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
	e.error(&UnsupportedTypeError{v.Type()})
}

type structEncoder struct {
	fields structFields
}

type structFields struct {
	list      []field
	nameIndex map[string]int
}

func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	next := byte('{')
FieldLoop:
	for i := range se.fields.list {
		f := &se.fields.list[i]

		// 按照f.index查找嵌套结构字段。
		fv := v
		for _, i := range f.index {
			if fv.Kind() == reflect.Pointer {
				if fv.IsNil() {
					continue FieldLoop
				}
				fv = fv.Elem()
			}
			fv = fv.Field(i)
		}

		if f.omitEmpty && isEmptyValue(fv) {
			continue
		}
		e.WriteByte(next)
		next = ','
		if opts.escapeHTML {
			e.WriteString(f.nameEscHTML)
		} else {
			e.WriteString(f.nameNonEsc)
		}
		opts.quoted = f.quoted
		f.encoder(e, fv, opts)
	}
	if next == '{' {
		e.WriteString("{}")
	} else {
		e.WriteByte('}')
	}
}

func newStructEncoder(t reflect.Type) encoderFunc {
	se := structEncoder{fields: cachedTypeFields(t)}
	return se.encode
}

type mapEncoder struct {
	elemEnc encoderFunc
}

func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	if v.IsNil() {
		e.WriteString("null")
		return
	}
	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
		// 我们有大量嵌套的PTR代码。对通话进行深度编码；
		// 开始检查我们是否进入了指针循环。
		ptr := v.Pointer()
		if _, ok := e.ptrSeen[ptr]; ok {
			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
		}
		e.ptrSeen[ptr] = struct{}{}
		defer delete(e.ptrSeen, ptr)
	}
	e.WriteByte('{')

	// 提取并排序密钥。
	sv := make([]reflectWithString, v.Len())
	mi := v.MapRange()
	for i := 0; mi.Next(); i++ {
		sv[i].k = mi.Key()
		sv[i].v = mi.Value()
		if err := sv[i].resolve(); err != nil {
			e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
		}
	}
	sort.Slice(sv, func(i, j int) bool { return sv[i].ks < sv[j].ks })

	for i, kv := range sv {
		if i > 0 {
			e.WriteByte(',')
		}
		e.string(kv.ks, opts.escapeHTML)
		e.WriteByte(':')
		me.elemEnc(e, kv.v, opts)
	}
	e.WriteByte('}')
	e.ptrLevel--
}

func newMapEncoder(t reflect.Type) encoderFunc {
	switch t.Key().Kind() {
	case reflect.String,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
	default:
		if !t.Key().Implements(textMarshalerType) {
			return unsupportedTypeEncoder
		}
	}
	me := mapEncoder{typeEncoder(t.Elem())}
	return me.encode
}

func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
	if v.IsNil() {
		e.WriteString("null")
		return
	}
	s := v.Bytes()
	e.WriteByte('"')
	encodedLen := base64.StdEncoding.EncodedLen(len(s))
	if encodedLen <= len(e.scratch) {
		// 如果编码的字节适合e.scratch，请避免额外的
		// 分配，并使用更便宜的编码。编码
		dst := e.scratch[:encodedLen]
		base64.StdEncoding.Encode(dst, s)
		e.Write(dst)
	} else if encodedLen <= 1024 {
		// 编码的字节足够短，无法分配，
		// 编码。编码还是比较便宜。
		dst := make([]byte, encodedLen)
		base64.StdEncoding.Encode(dst, s)
		e.Write(dst)
	} else {
		// 编码字节太长，无法廉价分配，
		// 编码。编码不再明显便宜。
		enc := base64.NewEncoder(base64.StdEncoding, e)
		enc.Write(s)
		enc.Close()
	}
	e.WriteByte('"')
}

// sliceEncoder只包装一个arrayEncoder，检查以确保值不是零。
type sliceEncoder struct {
	arrayEnc encoderFunc
}

func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	if v.IsNil() {
		e.WriteString("null")
		return
	}
	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
		// 我们有大量嵌套的PTR代码。对通话进行深度编码；
		// 开始检查我们是否进入了指针循环。
		// 在这里，我们使用一个结构来记忆指向片
		// 的第一个元素的指针及其长度。
		ptr := struct {
			ptr uintptr
			len int
		}{v.Pointer(), v.Len()}
		if _, ok := e.ptrSeen[ptr]; ok {
			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
		}
		e.ptrSeen[ptr] = struct{}{}
		defer delete(e.ptrSeen, ptr)
	}
	se.arrayEnc(e, v, opts)
	e.ptrLevel--
}

func newSliceEncoder(t reflect.Type) encoderFunc {
	// 字节片得到特殊处理；数组没有。
	if t.Elem().Kind() == reflect.Uint8 {
		p := reflect.PointerTo(t.Elem())
		if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
			return encodeByteSlice
		}
	}
	enc := sliceEncoder{newArrayEncoder(t)}
	return enc.encode
}

type arrayEncoder struct {
	elemEnc encoderFunc
}

func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	e.WriteByte('[')
	n := v.Len()
	for i := 0; i < n; i++ {
		if i > 0 {
			e.WriteByte(',')
		}
		ae.elemEnc(e, v.Index(i), opts)
	}
	e.WriteByte(']')
}

func newArrayEncoder(t reflect.Type) encoderFunc {
	enc := arrayEncoder{typeEncoder(t.Elem())}
	return enc.encode
}

type ptrEncoder struct {
	elemEnc encoderFunc
}

func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	if v.IsNil() {
		e.WriteString("null")
		return
	}
	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
		// 我们有大量嵌套的ptrEncoder。对通话进行深度编码；
		// 开始检查我们是否进入了指针循环。
		ptr := v.Interface()
		if _, ok := e.ptrSeen[ptr]; ok {
			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
		}
		e.ptrSeen[ptr] = struct{}{}
		defer delete(e.ptrSeen, ptr)
	}
	pe.elemEnc(e, v.Elem(), opts)
	e.ptrLevel--
}

func newPtrEncoder(t reflect.Type) encoderFunc {
	enc := ptrEncoder{typeEncoder(t.Elem())}
	return enc.encode
}

type condAddrEncoder struct {
	canAddrEnc, elseEnc encoderFunc
}

func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
	if v.CanAddr() {
		ce.canAddrEnc(e, v, opts)
	} else {
		ce.elseEnc(e, v, opts)
	}
}

// newCondAddrEncoder返回一个编码器，检查其值
// CanAddr是否委托给canAddrEnc，如果是，则委托给elseEnc。
func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
	enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
	return enc.encode
}

func isValidTag(s string) bool {
	if s == "" {
		return false
	}
	for _, c := range s {
		switch {
		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
			// 保留反斜杠和引号字符，但
			// 否则，允许在标记名中使用任何标点字符
			// 。
		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
			return false
		}
	}
	return true
}

func typeByIndex(t reflect.Type, index []int) reflect.Type {
	for _, i := range index {
		if t.Kind() == reflect.Pointer {
			t = t.Elem()
		}
		t = t.Field(i).Type
	}
	return t
}

type reflectWithString struct {
	k  reflect.Value
	v  reflect.Value
	ks string
}

func (w *reflectWithString) resolve() error {
	if w.k.Kind() == reflect.String {
		w.ks = w.k.String()
		return nil
	}
	if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok {
		if w.k.Kind() == reflect.Pointer && w.k.IsNil() {
			return nil
		}
		buf, err := tm.MarshalText()
		w.ks = string(buf)
		return err
	}
	switch w.k.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		w.ks = strconv.FormatInt(w.k.Int(), 10)
		return nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		w.ks = strconv.FormatUint(w.k.Uint(), 10)
		return nil
	}
	panic("unexpected map key type")
}

// 注意：与下面的stringBytes保持同步。
func (e *encodeState) string(s string, escapeHTML bool) {
	e.WriteByte('"')
	start := 0
	for i := 0; i < len(s); {
		if b := s[i]; b < utf8.RuneSelf {
			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
				i++
				continue
			}
			if start < i {
				e.WriteString(s[start:i])
			}
			e.WriteByte('\\')
			switch b {
			case '\\', '"':
				e.WriteByte(b)
			case '\n':
				e.WriteByte('n')
			case '\r':
				e.WriteByte('r')
			case '\t':
				e.WriteByte('t')
			default:
				// 除了\t、\n和\r之外，它编码的字节数<0x20。
				// 如果设置了escapeHTML，它也会转义<、>、和&
				// 因为当
				// 用户控制的字符串被呈现为JSON 
				// 并提供给一些浏览器时，它们可能会导致安全漏洞。
				e.WriteString(`u00`)
				e.WriteByte(hex[b>>4])
				e.WriteByte(hex[b&0xF])
			}
			i++
			start = i
			continue
		}
		c, size := utf8.DecodeRuneInString(s[i:])
		if c == utf8.RuneError && size == 1 {
			if start < i {
				e.WriteString(s[start:i])
			}
			e.WriteString(`\ufffd`)
			i += size
			start = i
			continue
		}
		// U+2028是行分隔符。
		// U+2029是段落分隔符。
		// 它们在JSON字符串中都是技术上有效的字符，
		// 但在JSONP中不起作用，JSONP必须评估为JavaScript，
		// 并可能导致安全漏洞。对
		// 进行转义是有效的JSON，所以我们无条件这么做。
		// 参见http:
		if c == '\u2028' || c == '\u2029' {
			if start < i {
				e.WriteString(s[start:i])
			}
			e.WriteString(`\u202`)
			e.WriteByte(hex[c&0xF])
			i += size
			start = i
			continue
		}
		i += size
	}
	if start < len(s) {
		e.WriteString(s[start:])
	}
	e.WriteByte('"')
}

// 注意：与上面的字符串保持同步。
func (e *encodeState) stringBytes(s []byte, escapeHTML bool) {
	e.WriteByte('"')
	start := 0
	for i := 0; i < len(s); {
		if b := s[i]; b < utf8.RuneSelf {
			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
				i++
				continue
			}
			if start < i {
				e.Write(s[start:i])
			}
			e.WriteByte('\\')
			switch b {
			case '\\', '"':
				e.WriteByte(b)
			case '\n':
				e.WriteByte('n')
			case '\r':
				e.WriteByte('r')
			case '\t':
				e.WriteByte('t')
			default:
				// 除了\t、\n和\r之外，它编码的字节数<0x20。
				// 如果设置了escapeHTML，它也会转义<、>、和&
				// 因为当
				// 用户控制的字符串被呈现为JSON 
				// 并提供给某些浏览器时，它们会导致安全漏洞。
				e.WriteString(`u00`)
				e.WriteByte(hex[b>>4])
				e.WriteByte(hex[b&0xF])
			}
			i++
			start = i
			continue
		}
		c, size := utf8.DecodeRune(s[i:])
		if c == utf8.RuneError && size == 1 {
			if start < i {
				e.Write(s[start:i])
			}
			e.WriteString(`\ufffd`)
			i += size
			start = i
			continue
		}
		// U+2028是行分隔符。
		// U+2029是段落分隔符。
		// 它们都是JSON字符串中的技术有效字符，
		// 但在JSONP中不起作用，JSONP必须评估为JavaScript，
		// 并可能导致安全漏洞。对
		// 来说，它是有效的JSON，所以我们无条件地这样做。
		// 请参见http:
		if c == '\u2028' || c == '\u2029' {
			if start < i {
				e.Write(s[start:i])
			}
			e.WriteString(`\u202`)
			e.WriteByte(hex[c&0xF])
			i += size
			start = i
			continue
		}
		i += size
	}
	if start < len(s) {
		e.Write(s[start:])
	}
	e.WriteByte('"')
}

// 字段表示在结构中找到的单个字段。
type field struct {
	name      string
	nameBytes []byte                 // /[]字节（名称）
	equalFold func(s, t []byte) bool // 字节。等倍或同等的

	nameNonEsc  string // /``+name+`:`
	nameEscHTML string // /```+HTMLEscape（name）+`:`

	tag       bool
	index     []int
	typ       reflect.Type
	omitEmpty bool
	quoted    bool

	encoder encoderFunc
}

// /按索引顺序对字段进行排序。
type byIndex []field

func (x byIndex) Len() int { return len(x) }

func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }

func (x byIndex) Less(i, j int) bool {
	for k, xik := range x[i].index {
		if k >= len(x[j].index) {
			return false
		}
		if xik != x[j].index[k] {
			return xik < x[j].index[k]
		}
	}
	return len(x[i].index) < len(x[j].index)
}

// typeFields返回JSON应该识别给定类型的字段列表。
// 该算法是对要包含的结构集进行广度优先搜索-顶部结构
// 然后是任何可到达的匿名结构。
func typeFields(t reflect.Type) structFields {
	// 在当前级别和下一级别探索的匿名字段。
	current := []field{}
	next := []field{{typ: t}}

	// 当前级别和下一级别的排队名称计数。
	var count, nextCount map[reflect.Type]int

	// 已在早期级别访问的类型。
	visited := map[reflect.Type]bool{}

	// 找到字段。
	var fields []field

	// 在字段名上运行HTMLEscape的缓冲区。
	var nameEscBuf bytes.Buffer

	for len(next) > 0 {
		current, next = next, current[:0]
		count, nextCount = nextCount, map[reflect.Type]int{}

		for _, f := range current {
			if visited[f.typ] {
				continue
			}
			visited[f.typ] = true

			// 扫描f.typ以查找要包含的字段。
			for i := 0; i < f.typ.NumField(); i++ {
				sf := f.typ.Field(i)
				if sf.Anonymous {
					t := sf.Type
					if t.Kind() == reflect.Pointer {
						t = t.Elem()
					}
					if !sf.IsExported() && t.Kind() != reflect.Struct {
						// 忽略未报告的非结构类型的嵌入字段。
						continue
					}
					// 不要忽略未报告结构类型的嵌入字段
					// 因为它们可能已导出字段。
				} else if !sf.IsExported() {
					// 忽略未报告的非嵌入字段。
					continue
				}
				tag := sf.Tag.Get("json")
				if tag == "-" {
					continue
				}
				name, opts := parseTag(tag)
				if !isValidTag(name) {
					name = ""
				}
				index := make([]int, len(f.index)+1)
				copy(index, f.index)
				index[len(f.index)] = i

				ft := sf.Type
				if ft.Name() == "" && ft.Kind() == reflect.Pointer {
					// 跟随指针。
					ft = ft.Elem()
				}

				// 只能引用字符串、浮点数、整数和布尔值。
				quoted := false
				if opts.Contains("string") {
					switch ft.Kind() {
					case reflect.Bool,
						reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
						reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
						reflect.Float32, reflect.Float64,
						reflect.String:
						quoted = true
					}
				}

				// 记录找到的字段和索引序列。
				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
					tagged := name != ""
					if name == "" {
						name = sf.Name
					}
					field := field{
						name:      name,
						tag:       tagged,
						index:     index,
						typ:       ft,
						omitEmpty: opts.Contains("omitempty"),
						quoted:    quoted,
					}
					field.nameBytes = []byte(field.name)
					field.equalFold = foldFunc(field.nameBytes)

					// 提前构建NamesHTML和nameNonEsc。
					nameEscBuf.Reset()
					nameEscBuf.WriteString(`"`)
					HTMLEscape(&nameEscBuf, field.nameBytes)
					nameEscBuf.WriteString(`":`)
					field.nameEscHTML = nameEscBuf.String()
					field.nameNonEsc = `"` + field.name + `":`

					fields = append(fields, field)
					if count[f.typ] > 1 {
						// 如果有多个实例，请添加第二个，
						// 这样湮灭代码将看到一个副本。
						// 它只关心1或2之间的区别，
						// 所以不要再麻烦生成任何副本。
						fields = append(fields, fields[len(fields)-1])
					}
					continue
				}

				// 记录新的匿名结构，以便在下一轮中进行探索。
				nextCount[ft]++
				if nextCount[ft] == 1 {
					next = append(next, field{name: ft.Name(), index: index, typ: ft})
				}
			}
		}
	}

	sort.Slice(fields, func(i, j int) bool {
		x := fields
		// 按名称排序字段，与深度断开联系，然后
		// 与“名称来自json标记”断开联系，然后
		// 与索引序列断开联系。
		if x[i].name != x[j].name {
			return x[i].name < x[j].name
		}
		if len(x[i].index) != len(x[j].index) {
			return len(x[i].index) < len(x[j].index)
		}
		if x[i].tag != x[j].tag {
			return x[i].tag
		}
		return byIndex(x).Less(i, j)
	})

	// 删除所有被嵌入字段的Go规则隐藏的字段，
	// 除非带有JSON标记的字段被提升。

	// 字段按名称的主顺序排序，按字段索引长度的次顺序
	// 排序。在名字上循环；对于每个名称，通过选择一个幸存的主要字段，删除
	// 隐藏字段。
	out := fields[:0]
	for advance, i := 0, 0; i < len(fields); i += advance {
		// 每个名称迭代一次。
		// 查找具有第一个字段名称的字段序列。
		fi := fields[i]
		name := fi.name
		for advance = 1; i+advance < len(fields); advance++ {
			fj := fields[i+advance]
			if fj.name != name {
				break
			}
		}
		if advance == 1 { // 只有一个字段名为
			out = append(out, fi)
			continue
		}
		dominant, ok := dominantField(fields[i : i+advance])
		if ok {
			out = append(out, dominant)
		}
	}

	fields = out
	sort.Sort(byIndex(fields))

	for i := range fields {
		f := &fields[i]
		f.encoder = typeEncoder(typeByIndex(t, f.index))
	}
	nameIndex := make(map[string]int, len(fields))
	for i, field := range fields {
		nameIndex[field.name] = i
	}
	return structFields{fields, nameIndex}
}

// dominantField查看所有字段（所有字段都是
// 具有相同名称），以找到支配
// 的单个字段。其他字段使用Go的嵌入规则，通过存在
// JSON标记进行修改。如果有多个顶级字段，则布尔值
// 将为false：此条件在Go中是一个错误，我们将跳过所有
// 字段。
func dominantField(fields []field) (field, bool) {
	// 字段按索引长度递增的顺序排序，然后按标记的存在进行排序。
	// 这意味着第一个字段是主导字段。我们只需要检查
	// 是否存在错误情况：顶层有两个字段，要么都有标记，要么都没有标记。
	if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
		return field{}, false
	}
	return fields[0], true
}

var fieldCache sync.Map // map[reflect.Type]structFields 

// cachedTypeFields与typeFields类似，但使用缓存来避免重复工作。
func cachedTypeFields(t reflect.Type) structFields {
	if f, ok := fieldCache.Load(t); ok {
		return f.(structFields)
	}
	f, _ := fieldCache.LoadOrStore(t, typeFields(t))
	return f.(structFields)
}
